﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FluentScheduler;
using ComUIControl;
using System.Threading.Tasks;
using LogLib;
using System.IO;
using ComLib.ComFun;

namespace ScheduleAutoAction
{
    public partial class ucScheduleCleaning : UserControl
    {
        private readonly string ScheduleCleanName = "OnPhotoCleaning";

        private readonly string ScheduleQueryName = "PreparingForCleaning";

        public decimal _dDriveTotalSpace;
        public decimal _dDriveOccupySpace;
        public decimal _dDriveFreeSpace;
        public decimal _dSPCOccupySpace;

        private ScheduleCleaningOption _option = new ScheduleCleaningOption();
        public ScheduleCleaningOption Option
        {
            get { return _option; }
        }

        private Cleaner _cleaner = null;

        public ucScheduleCleaning()
        {
           
            InitializeComponent();
        }

        private void LoadConfig()
        {
            if (!File.Exists(_option.ConfigFilePath))
            {
                _option.Save();
            }      
            _option.Load();
        }
        //private void OnFormNormal()
        //{
        //    if (this.InvokeRequired)
        //    {
        //        Action outdelegate = new Action(OnFormNormal);
        //        this.BeginInvoke(outdelegate, new object[] { });
        //        return;
        //    }
        //    this.WindowState = FormWindowState.Normal;
        //    this.Activate();
        //    this.ShowInTaskbar = true;
        //    this.notifyIcon1.Visible = false;
        //    Rectangle rect = new Rectangle();
        //    rect = Screen.GetWorkingArea(this);
        //    int width = rect.Width;//屏幕宽
        //    int height = rect.Height;//屏幕高
        //    int x = (width - this.Width) / 2;
        //    int y = (height - this.Height) / 2;
        //    this.Location = new Point(x, y);
        //}

        private void InitCtrls()
        {
            if (_option.Enabled)
            {
                buttonStart.Visible = false;
                buttonStop.Visible = true;
            }
            else
            {
                buttonStart.Visible = true;
                buttonStop.Visible = false;
                buttonStart.Location = buttonStop.Location;
            }

        }

        public void Init()
        {            
            Log.AddBeginningBoundary();
            LoadConfig();
            _cleaner = new Cleaner(_option);
            _cleaner.SetDelegateFun(
                GetCleaningPermit,
                UpdateRemoveState,
                UpdateTextBox,
                AfterQuery,
                AfterClear,
                UpdateStatusIcon);
            UpdateSpaceInfo();
            InitCtrls();
            if (_option.Enabled)
            {
                StartSchedule();
            }
            else
            {
                _cleaner.Init();
            }
        }

        private void UpdateStatusIcon(OperateStatus s)
        {
            if (this.InvokeRequired)
            {
                UpdateStatusIconHandler outdelegate = new UpdateStatusIconHandler(UpdateStatusIcon);
                this.BeginInvoke(outdelegate, new object[] { s });
                return;
            }
            string imagePath = string.Format("{0}//CleanStateImage//", Application.StartupPath);
            switch (s)
            {
                case OperateStatus.None:
                    imagePath = imagePath + "none.png";
                    pictureBox1.Image = Image.FromFile(imagePath);
                    UpdateRemoveState("当前无任务计划");
                    break;
                case OperateStatus.Query:
                    buttonClear.Enabled = false;
                    buttonStop.Enabled = false;             
                    imagePath = imagePath + "query.gif";
                    pictureBox1.Image = Image.FromFile(imagePath);
                    UpdateRemoveState("正在查找可以清理的文件...");
                    break;
                case OperateStatus.QueryFailed:
                    imagePath = imagePath + "info.png";
                    pictureBox1.Image = Image.FromFile(imagePath);
                    UpdateRemoveState("没有可清理的文件.");
                    break;
                case OperateStatus.Ready:
                    imagePath = imagePath + "starting.png";
                    pictureBox1.Image = Image.FromFile(imagePath);
                    UpdateRemoveState("准备就绪");
                    break;
                case OperateStatus.Running:
                    buttonCancellClear.Visible = true;
                    buttonClear.Enabled = false;
                    buttonStop.Enabled = false;                  
                    imagePath = imagePath + "running.gif";
                    pictureBox1.Image = Image.FromFile(imagePath);
                    break;
                case OperateStatus.Finished:
                    imagePath = imagePath + "finished.png";
                    pictureBox1.Image = Image.FromFile(imagePath);
                    UpdateRemoveState("清理完成");
                    break;
                case OperateStatus.Exception:
                    imagePath = imagePath + "sad.png";
                    pictureBox1.Image = Image.FromFile(imagePath);
                    UpdateRemoveState("清理过程发生了异常");
                    break;
                case OperateStatus.Cancell:
                    imagePath = imagePath + "cancell.png";
                    pictureBox1.Image = Image.FromFile(imagePath);
                    UpdateRemoveState("用户中断了清理");
                    break;
                default:
                    break;
            }
            Schedule schedule = JobManager.GetSchedule(ScheduleCleanName);
            if (schedule != null)
            {
                DateTime dt = schedule.NextRun;
                labelNextPlan.Text = string.Format("下一次清理任务计划将于 {0} 执行", dt.ToString("yyyy年MM月dd日 HH:mm:ss"));
            }
            else
            {
                labelNextPlan.Text = "当前没有任何任务计划";
            }
        }

        /// <summary>
        /// 获得清理许可
        /// </summary>
        /// <returns></returns>
        private bool GetCleaningPermit()
        {
            if (this.InvokeRequired)
            {
                GetBooleanResultHandler outdelegate = new GetBooleanResultHandler(GetCleaningPermit);
                bool result = (bool)this.Invoke(outdelegate, new object[] { });
                return result;
            }
            if (_option.Enquiring)
            {
                if (MessageBox.Show("即将执行自动清理，清理的记录将不可恢复.\n 确定要清理吗?"
                  , "是否清理"
                  , MessageBoxButtons.OKCancel
                  , MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 显示错误信息
        /// </summary>
        /// <returns></returns>
        private void ShowErrorMessage(string message)
        {
            if (this.InvokeRequired)
            {
                UpdateTextHandler outdelegate = new UpdateTextHandler(ShowErrorMessage);
                this.BeginInvoke(outdelegate, new object[] { message });
            }
           MessageBox.Show(message
                       , "错误提示"
                       , MessageBoxButtons.OK
                       , MessageBoxIcon.Error);
        }

        private void AfterQuery()
        {
            if (this.InvokeRequired)
            {
                Action outdelegate = new Action(AfterQuery);
                this.BeginInvoke(outdelegate, new object[] { });
                return;
            }
            buttonStop.Enabled = true;
            buttonClear.Enabled = true;
            UpdateStatusIcon(_cleaner.Status);
            UpdateRemoveState(_cleaner.OperateMessage);
            UpdateTextBox(_cleaner.OperateMessage);
        }

        private void CalculateDiskCapacity()
        {
            // 计算D盘占用空间
            DriveInfo dInfo = DiskOperator.GetDriveInfo("D:\\");
            _dDriveFreeSpace = (decimal)dInfo.TotalFreeSpace / DiskOperator.GB;
            _dDriveTotalSpace = (decimal)dInfo.TotalSize / DiskOperator.GB;
            _dDriveOccupySpace = _dDriveTotalSpace - _dDriveFreeSpace;

            _dDriveTotalSpace = System.Decimal.Round(_dDriveTotalSpace, 0);
            _dDriveFreeSpace = System.Decimal.Round(_dDriveFreeSpace, 2);
            _dDriveOccupySpace = System.Decimal.Round(_dDriveOccupySpace, 2);

            decimal pv = _dDriveOccupySpace / _dDriveTotalSpace * 100;
            pv = System.Decimal.Round(pv, 0);
            int per = (int)pv;
            metroProgressBar1.Value = per;
        }

        private void CalculateDirectoryCapacity()
        {
            // 检查磁盘空间
            string directory = _cleaner.PhotoSaveDirectory;
            long totalSpace = DiskOperator.GetDirectorySpace(directory);

            _dSPCOccupySpace = (decimal)totalSpace / DiskOperator.GB;
            _dSPCOccupySpace = System.Decimal.Round(_dSPCOccupySpace, 3);
        }

        private void UpdateSpaceInfo()
        {
            if (this.InvokeRequired)
            {
                Action outdelegate = new Action(UpdateSpaceInfo);
                this.BeginInvoke(outdelegate, new object[] { });
                return;
            }
            CalculateDiskCapacity();
            CalculateDirectoryCapacity();
            labelSpaceInfo.Text =
                string.Format("共{0}GB, 已用{1}GB, 包含照片{2}GB, 剩余可用{3}GB.",
                _dDriveTotalSpace,
                _dDriveOccupySpace,
                _dSPCOccupySpace,
                _dDriveFreeSpace);
        }

        private void AfterClear()
        {
            if (this.InvokeRequired)
            {
                Action outdelegate = new Action(AfterClear);
                this.BeginInvoke(outdelegate, new object[] { });
                return;
            }
            buttonStop.Enabled = true;
            buttonClear.Enabled = true;      
            buttonCancellClear.Visible = false;
            UpdateStatusIcon(_cleaner.Status);
            UpdateRemoveState(_cleaner.OperateMessage);
            UpdateTextBox(_cleaner.OperateMessage);
            UpdateSpaceInfo();
            if (_option.IntervalTime == ExecutionInterval.ApplicationStart || _option.IntervalTime == ExecutionInterval.ApplicationExit)
            {
                //this.Close();
            }
            else
            {
                timer1.Enabled = true;
            }
        }

        private void UpdateRemoveState(string val)
        {
            if (this.InvokeRequired)
            {
                UpdateTextHandler outdelegate = new UpdateTextHandler(UpdateRemoveState);
                this.BeginInvoke(outdelegate, new object[] { val });
                return;
            }
            labelNowStatus.Text = val;
            labelNowStatus.Left = (panel1.Width - labelNowStatus.Width) / 2;
        }


        private DayOfWeek GetWeekDay()
        {
            DayOfWeek day = DayOfWeek.Sunday;
            if (_option.ExecuteWeekDay != ExecutionWeekDay.Sunday)
            {
                int val = (int)_option.ExecuteWeekDay;
                day = (DayOfWeek)(val + 1);
            }
            return day;
        }

        private void StartSchedule()
        {
            Registry registry = new Registry();
            Schedule schedule = registry.Schedule(() => _cleaner.Clear());
            int hour = _option.ExecuteTime.Hour;
            int minute = _option.ExecuteTime.Minute;
            DayOfWeek day = GetWeekDay();
            switch (_option.IntervalTime)
            {
                case ExecutionInterval.DayOnce:
                    schedule.WithName(ScheduleCleanName).ToRunEvery(1).Days().At(hour, minute);
                    break;
                case ExecutionInterval.WeekOnce:
                    schedule.WithName(ScheduleCleanName).ToRunEvery(0).Weeks().On(day).At(hour, minute);
                    break;
                case ExecutionInterval.MonthOnce:
                    schedule.WithName(ScheduleCleanName).ToRunEvery(1).Months().OnTheFirst(day).At(hour, minute);
                    break;
                case ExecutionInterval.ApplicationStart:
                case ExecutionInterval.ApplicationExit:
                    schedule.WithName(ScheduleCleanName).ToRunOnceIn(3).Seconds();
                    break;
                default:
                    break;
            }
            JobManager.JobStart += (info) => Log.WriteAsync(info.Name + "开始");
            JobManager.JobEnd += (info) => Log.WriteAsync(info.Name + "结束");
            JobManager.JobException += (info) => Log.WriteAsync("[job exception]: " + info.Exception);
            JobManager.Initialize(registry);
            JobManager.AddJob(() => _cleaner.Query(), s => s.WithName(ScheduleQueryName).ToRunNow().AndEvery(1).Hours());
        }

        public void OnManualClear()
        {
            WaitingBox.Show("正在清理，请稍候...");
            TaskScheduler taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            Task.Factory.StartNew(
                () => _cleaner.Clear()
                    ).ContinueWith((t) =>
                    {
                        WaitingBox.Close();
                    }, taskScheduler);
        }

        private void buttonClear_Click(object sender, EventArgs e)
        {
            OnManualClear();
        }

        private void buttonCancellClear_Click(object sender, EventArgs e)
        {
            if (_cleaner != null && _cleaner.Status == OperateStatus.Running)
            {
                _cleaner.CancellClearing();
            }
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            StartSchedule();
            buttonStop.Visible = true;
            buttonStart.Visible = false;
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            StopAndRemoveSchedule();
            buttonStop.Visible = false;
            buttonStart.Visible = true;
            buttonStart.Location = buttonStop.Location;
        }

        public void StopAndRemoveSchedule()
        {
            JobManager.RemoveJob(ScheduleCleanName);
            JobManager.RemoveJob(ScheduleQueryName);
            JobManager.RemoveAllJobs();
            _cleaner.Init();
            UpdateTextBox("用户取消了任务计划.");
        }

        private void UpdateTextBox(string val)
        {
            try
            {
                if (this.InvokeRequired)
                {
                    Action<string> outdelegate = new Action<string>(UpdateTextBox);
                    this.BeginInvoke(outdelegate, new object[] { val });
                    return;
                }
                this.richTextBox1.AppendText(DateTime.Now.ToString("HH:mm:ss ") + val + Environment.NewLine);
                this.richTextBox1.SelectionStart = this.richTextBox1.TextLength;
                this.richTextBox1.ScrollToCaret();
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
        }
    }
}
